#!/usr/bin/python
# Created by Juan C. Espinoza <jucar.espinoza@gmail.com> October 05, 2009

import os, re, shutil, zipfile
from lisn_utils import GPSDateTime, timedelta, LISNRequest, Hatanaka, RNXData, MyFTP
import argparse

#Variables

database_gps = '/data1/gps/'
request = LISNRequest(debug=False)
params = request.params

rnx_pattern = {
                'montecillo' : '_%y%m%d.%yd.tar.gz',
                'capricorn2' : '_%y%m%d.%yd.tar.gz',
                'sirgas' : '%j%y',
                'unavco' : '%j0.%yd.Z',
                'rbmc'   : '%j1.zip'
              }

htnk = Hatanaka()

def copy_file(old_name, new_name, site, date):
    '''
    '''
    
    path = os.path.join(database_gps, site['network'], site['code'],
                                date.strftime('%Y/%m/rinex'))
    if not os.path.exists(path):
        os.makedirs(path)
    
    if site['server'] in ('montecillo', 'capricorn2'):
        try:
            old_rinex = RNXData(old_name)
        except:
            print 'Error parsing file'
            return False            
    
        if os.path.exists(new_name):
            print 'File %s already exists -> merging...' % new_name
            tmp_rinex = RNXData(new_name)
            print ' records in %s : %s' % (old_name, len(old_rinex))
            print ' records in %s : %s' % (new_name, len(tmp_rinex))
            old_rinex.merge(tmp_rinex)
        
        
        header = old_rinex.header    
        kwargs = {'xyz'          : header['markerpos'][0],
                  'receivertype' : site['info']['receiver'],
                  'receiverver'  : site['info']['receiver_firmware'],
                  'receivernum'  : site['info']['receiver_number'],
                  'antennatype'  : site['info']['antenna'],
                  'antennanum'   : site['info']['antenna_number'],
                  'comment'      : 'Location: %s\n' % site['fullname']}
    
        try:
            new_rinex, nrec = old_rinex.save(path, site['code'], **kwargs)
            htnk.compress(new_rinex, True, True)
        except:
            return False
    
    elif site['server'] in ('rbmc',):
        zfile = zipfile.ZipFile(old_name)
        obs = [zip.filename for zip in zfile.filelist if re.search('\.[0-9]{2}[o]$', zip.filename)]
        if obs:
            old_rinex = zfile.open(obs[0])
            new_rinex = open(new_name[:-3]+'o', 'wb')
            new_rinex.write(old_rinex.read())
            new_rinex.close()
            htnk.compress(new_name[:-3]+'o', True, True)
    elif site['server'] in ('unavco',):        
        shutil.copy(old_name, new_name)
    else:
        return False
    
    return new_name


def get_files(vars, date, FTP):
    '''
    Get RINEX files from servers    
    '''
    
    sites = request.stations(server=vars.server, instrument='gps')
    
    if vars.sites:
        sites = [s for s in sites if s['code'] in vars.sites]    
        
    if not FTP.error:
        for site in sites:
            kwargs = {}
            name = '%s%s' % (site['code'], date.strftime('%j0.%yd.Z'))
            path = os.path.join(database_gps, site['network'], site['code'],
                                date.strftime('%Y/%m/rinex'))
            new_name = os.path.join(path, name)
            if not vars.overwrite and os.path.exists(new_name):
                print '%s Already exists!' % new_name
                continue
            if vars.server in ('montecillo', 'capricorn2'):
                filename = site['lisn_code']+date.strftime(rnx_pattern[vars.server])
            else:
                filename = site['code']+date.strftime(rnx_pattern[vars.server])
            remote_file = os.path.join(vars.root, filename)                
            try:                    
                tmp_file = os.path.join(vars.temp, filename)
                FTP.download(remote_file, tmp_file)
                new_rinex = copy_file(tmp_file, new_name, site, date)
                if new_rinex and vars.remove:
                    print 'Deleting file: %s' % remote_file
                    FTP.remove(remote_file)
                if new_rinex:
                    kwargs['last_file_date'] = date.strftime('%y%m%d')
                    kwargs['last_file'] = new_rinex.split('/')[-1]
                    kwargs['state'] = 1
                    kwargs2 = {'date': date.strftime('%y%m%d')}
                    req = request.update_date(site['code'], 'gps', 'rinex', **kwargs2)                  
            except:
                print 'Error getting file: %s ' % remote_file
                kwargs['state'] = 2
            
            if os.path.exists(tmp_file):
                os.remove(tmp_file)    
            
            if vars.server not in ('montecillo', 'capricorn2') and vars.daily:
                req = request.update_station(site['code'], 'gps', **kwargs)
    else:
        print 'Error in connection'

def main():
    '''
    Parse arguments to program.
    '''

    parser = argparse.ArgumentParser(description=main.func_doc)    
    # add options and arguments
    parser.add_argument('dates', nargs='*', default=[],
            help='Period of time to be processed (start and end date) fmt:yy,mm,dd')
    # add options and arguments
    parser.add_argument('-S', '--server', action='store', choices=params.rinex_server().keys(),
            help='server ID')
    parser.add_argument('-s', '--sites', action='store', 
            help='stations codes')
    parser.add_argument('-t', action='store', dest='temp', default='/data/temp/rinex/',
            help='Path for temporary files')
    parser.add_argument('-r', '--remove', action='store_true',
            help='Remove ftp file on the server')
    parser.add_argument('-o', '--overwrite', action='store_true',
            help='Overwrite (merge) local file if exists')
    
    opts = parser.parse_args()

    if not opts.server:
        parser.error('Server option is mandatory')
      
    if len(opts.dates)>0 :
        try:
            opts.daily = False
            date_1 = GPSDateTime(opts.dates[0])
            if len(opts.dates) == 2:
                date_2 = GPSDateTime(opts.dates[1])
            else:
                date_2 = date_1
        except:
            parser.error('Dates can not be parsed fmt: yyyy,mm,dd')
    else:
        date_1 = GPSDateTime().date()-timedelta(1)
        date_2 = date_1
        opts.daily = True

    [host, username, password, opts.root, sftp] = params.rinex_server(opts.server)
    
    if password == 'key':
        havekey = True
    else:
        havekey = False

    FTP = MyFTP(host, username, password, sftp, havekey)

    while date_1<=date_2:
        opts.root = date_1.strftime(opts.root)
        get_files(opts, date_1, FTP)
        date_1 += timedelta(1)
    
    FTP.close()

#Execute main routine
if __name__ == "__main__":
    dt = GPSDateTime()
    print '\n Start at %s' % dt.ctime()
    main()
    print '\n Total secs: %s' % (GPSDateTime()-dt)